package com.wx.spring;

import com.wx.cache.ChannelCache;
import com.wx.cache.LouckCache;
import com.wx.cache.ResponseCache;
import com.wx.content.DataType;
import com.wx.network.codec.RpcProtocol;
import com.wx.network.mesg.Request;
import com.wx.util.SerializationUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
@Slf4j
public class JdkProxyInvocationHandler implements InvocationHandler {

    public Class<?> targetInterface;
    public String serverName;

    public JdkProxyInvocationHandler(Class<?> targetInterface, String serverName) {
        this.targetInterface = targetInterface;
        this.serverName = serverName;
    }

    public JdkProxyInvocationHandler(Class<?> targetInterface){
        this.targetInterface=targetInterface;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        Class[] paramTypes = method.getParameterTypes();
        if ("toString".equals(methodName) && paramTypes.length == 0) {
            return proxy.toString();
        } else if ("hashCode".equals(methodName) && paramTypes.length == 0) {
            return proxy.hashCode();
        } else if ("equals".equals(methodName) && paramTypes.length == 1) {
            return proxy.equals(args[0]);
        }

        //开始远程调用，去缓存里面同通过注解获得需要调用服务的channel
        Channel channel = ChannelCache.getChannel(serverName);
        //构建请求
        RpcProtocol rpcProtocol = new RpcProtocol();
        Request request = new Request();
        String requestId = UUID.randomUUID().toString();

        Class<?>[] parameterTypes = method.getParameterTypes();
        //获得需要方法的名字转小写
        String className = method.getDeclaringClass().getName();

        String[] split = className.split("\\.");
        int length = split.length;
        String s = split[length - 1];
        String s1 = (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
        request.setConsumerInterface(s1);
        request.setRequestId(requestId);
        request.setMethodName(methodName);
        request.setDataType(DataType.BUSSINESS);
        request.setAges(args);
        request.setParamTypes(parameterTypes);
        byte[] bytes = SerializationUtil.serialzationObj(request);
        rpcProtocol.setData(bytes);
        rpcProtocol.setLength(bytes.length);
        //开始调用
        log.info("{}方法开始调用，id是{}",methodName,requestId);
        CountDownLatch countDownLatch = new CountDownLatch(1);
        log.info("放入线程私有的是{}",countDownLatch);
        LouckCache.put(requestId,countDownLatch);
        ChannelFuture future = channel.writeAndFlush(rpcProtocol);
        //先后顺序
        Object cache = ResponseCache.getCache(requestId, countDownLatch);
        //todo 获得调用结果
        return cache;
    }
}
